package com.zdy.socketserver.client;

/**
 * @author myh
 * @date 2024/6/11
 */

import com.alibaba.fastjson.JSON;
import com.zdy.socketserver.sound.Sound;
import io.netty.handler.codec.http.websocketx.WebSocketClientProtocolHandler;
import io.netty.channel.*;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

@Component
public class MyWebSocketClientHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    private static final Logger log = LoggerFactory.getLogger(Sound.class);

//    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
//
//
//    private ScheduledFuture<?> pingTimeoutFuture;

    private NettyClient nettyClient;

    public MyWebSocketClientHandler(NettyClient nettyClient) {
        this.nettyClient = nettyClient;

    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {

    }

    /**
     * 通道激活之后回调方法
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("连接服务器成功");
    }
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof WebSocketClientProtocolHandler.ClientHandshakeStateEvent) {
            // WebSocket握手成功回调
            log.info("WebSocket握手成功");
            // 握手成功后发送消息
            sendClientTypeMessage(ctx.channel());
        }else{
            super.userEventTriggered(ctx, evt);
        }
    }

    /**
     * 通道关闭回调方法
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("客户端关闭连接");
        //重连重新生成一个通道
        ctx.pipeline().remove(this);
        ctx.channel().close();
        nettyClient.connect();
    }

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame msg) throws Exception {
        if("ping".equals(msg.text())){
            log.info("收到ping消息");
            channelHandlerContext.writeAndFlush(new TextWebSocketFrame("pong"));
            log.info("发送pong消息");
        } else{
            log.info("客户端接收到消息：" + msg.text());
            Sound sound = new Sound();
            sound.call(msg.text());
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        log.info("客户端关闭连接");
        //重连重新生成一个通道
        ctx.pipeline().remove(this);
        ctx.channel().close();
        nettyClient.connect();
    }
    private void sendClientTypeMessage(Channel channel) {
        try {
            String macAddress = NettyClient.getMACAddress();
            // 创建客户端类型消息
            Map<String,Object> map = new HashMap<>();
            map.put("clientType", ClientType.SPEAKER.getTypeValue());
            map.put("num",macAddress);
            TextWebSocketFrame frame = new TextWebSocketFrame(JSON.toJSONString(map));
            channel.writeAndFlush(frame);
            log.info("客户端类型消息发送成功，mac地址为{}",macAddress);
        }catch (Exception e){
            log.info("获取mac地址异常");
            e.printStackTrace();
        }

    }
}
